/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package semantic_network;

import file_handler.File_Manager;
import java.util.Vector;



public class Resource_Handler
{
    private Vector<String> resources = new Vector();
    private Vector resource_freq = new Vector();
    private Vector[] resource_profile_array;

    private File_Manager fileManager = new File_Manager();
    private Vector_Manipulation vector_builder = new Vector_Manipulation();

    private SQL_Handler_Network sql_handler_1 = new SQL_Handler_Network();
    private SQL_Handler_Network sql_handler_2 = new SQL_Handler_Network();

    private Descriptor_Handler descriptor_processor = new Descriptor_Handler(sql_handler_1, sql_handler_2);


    /*
     * Initialize the two instances of database connections in constructor.
     * The two connections correspond to the two databases; bmc_2009 & bmc_2009_2
     */
    public Resource_Handler(String database_url_1,String database_url_2, String username, String password)
    {
        sql_handler_1.initialize_parameters(database_url_1,username,password);
        sql_handler_2.initialize_parameters(database_url_2,username,password);
    }

    /**
     * Reads the list of resource names from a text file (the path of the file is
     * set in Properties file, and is retrieved from file using DESCRIPTORS_PATH in Main class)
     * It calls for lexical profiles of resource names and their frequencies.
     * @param descriptors_path Stores the path of file containing list of descriptors
     */
    public void retrieve_resources_from_disk(String descriptors_path)
    {
        StringBuffer file_contents = fileManager.fileReader(descriptors_path);
        System.out.println("Resources : \n" + file_contents);

        resources = vector_builder.keyword_to_vector(file_contents.toString(), "\n");
        make_resource_name_profiles();
        calculates_resources_freq();
    }

    /*
     * It measures and stores the lexical profile of resource names into an array of vectors.
     * Each vector stores the lexical profile of one resource name
     */
    private void make_resource_name_profiles()
    {
        // The constituents are used to measure lexical profile based comparison of resource names
        resource_profile_array = new Vector[resources.size()];

        for (int i = 0; i < resources.size(); i++)
        {
            String resource_name = resources.elementAt(i).toString();
            resource_profile_array[i] = vector_builder.make_term_profiles(resource_name);
            resource_profile_array[i].add(resource_name.toLowerCase());
        }

    }

    public void extract_descriptors()
    {
        descriptor_processor.extract_descriptors(resources);
    }
    
    /*
     * It calculates the frequency of resource names. The data is provided in database "bmc_2009".
     */
    private void calculates_resources_freq()
    {
        sql_handler_1.connect_db();
        for (String resource_name : resources)
        {
            resource_freq.add(sql_handler_1.get_resource_name_freq(resource_name));
        }
        System.out.println("Value resources : " + resources.toString() + " Freq is : " + resource_freq.toString());
        sql_handler_1.close_db();
    }



    /**
     * Matches the resources based on their descriptors without considering the 
     * tf*idf. It exports the output to txt files which are used by Cytoscape software
     * to develop the semantic network.
     * It uses binary values to measure the similarity (unlike the
     * resource_matching_using_idf which uses inverse descriptor frequencies.
     * 
     * @param mode Tells which method of comparison is being used to measure the relevance of resources.
     * Possible values of mode are "Method2" and "Method3"
     */
    public void resource_matching_using_descriptors(String mode,String similarity_metric)
    {

        StringBuffer file_contents_index = new StringBuffer("");
        StringBuffer file_contents_freq = new StringBuffer("");
        file_contents_index.append("names \n");
        file_contents_freq.append("freq \n");


        StringBuffer file_contents_nodes_method2 = new StringBuffer("");
        StringBuffer file_contents_edges_method2 = new StringBuffer("");
        StringBuffer file_contents_similarity_method2 = new StringBuffer("");

        StringBuffer file_contents_nodes_method3 = new StringBuffer("");
        StringBuffer file_contents_edges_method3 = new StringBuffer("");
        StringBuffer file_contents_similarity_method3 = new StringBuffer("");


        file_contents_edges_method2.append("similarity_2 \n");
        file_contents_edges_method3.append("similarity_3 \n");

        file_contents_similarity_method2.append("similarity_2 \n");
        file_contents_similarity_method3.append("similarity_3 \n");

        for (int i = 0; i < resources.size(); i++)
        {
            String resource1 = resources.elementAt(i).toString();
            String resource1_abbreviation = resource_name_mapper(resource1);
            
            String frequency_1 = resource_freq.elementAt(i).toString();
            Vector descriptors1 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_array()[i].toString());
            int size1 = descriptors1.size();

            file_contents_index.append("n" + i + " = " + resource1_abbreviation + "\n");
            file_contents_freq.append("n" + i + " = " + frequency_1 + "\n");

            for (int j = i + 1; j < resources.size(); j++)
            {
                String resource2 = resources.elementAt(j).toString();
                Vector descriptors2 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_array()[j].toString());
                int size2 = descriptors2.size();

                double similarity_method2 = descriptor_processor.match_descriptors(descriptors1, descriptors2);
                double similarity_method3 = descriptor_processor.match_descriptors_using_lexical_profiles(descriptors1, descriptors2,similarity_metric);


                /***** Measure the similarity value for Method2 *****/

                if (mode.equals("Method2"))
                {
                    if (similarity_method2 > 0)
                    {
                        if (similarity_metric.equals("COSINE"))
                        {
                            file_contents_edges_method2.append("n" + i + " (s) n" + j + " = "
                                    + (double) (similarity_method2) / (size1 * size2) + "\n");

                            file_contents_similarity_method2.append(resource1 + " (sim) " + resource2 + " = "
                                    + (double) (similarity_method2) / (size1 * size2) + "\n");

                            file_contents_nodes_method2.append("n" + i + " s n" + j + "\n");
                        } 
                        else if (similarity_metric.equals("DICE"))
                        {
                            file_contents_edges_method2.append("n" + i + " (s) n" + j + " = "
                                    + (double) (2 * similarity_method2) / (size1 + size2) + "\n");

                            file_contents_similarity_method2.append(resource1 + " (sim) " + resource2 + " = "
                                    + (double) (similarity_method2) / (size1 + size2) + "\n");

                            file_contents_nodes_method2.append("n" + i + " s n" + j + "\n");
                        }
                    }
                }
                
                /***** Measure the similarity value for Method3 *****/
                if (mode.equals("Method3"))
                {
                    if (similarity_method3 > 0)
                    {
                        if (similarity_metric.equals("COSINE"))
                        {
                            file_contents_edges_method3.append("n" + i + " (s) n" + j + " = "
                                    + (double) (similarity_method3) / (size1 * size2) + "\n");

                            file_contents_similarity_method3.append(resource1 + " (sim) " + resource2 + " = "
                                    + (double) (similarity_method3) / (size1 * size2) + "\n");

                            file_contents_nodes_method3.append("n" + i + " s n" + j + "\n");
                        } 
                        else if (mode.equals("DICE"))
                        {
                            file_contents_edges_method3.append("n" + i + " (s) n" + j + " = "
                                    + (double) (similarity_method3) / (size1 + size2) + "\n");

                            file_contents_similarity_method3.append(resource1 + " (sim) " + resource2 + " = "
                                    + (double) (similarity_method3) / (size1 + size2) + "\n");

                            file_contents_nodes_method3.append("n" + i + " s n" + j + "\n");
                        }
                    }
                }
            }

            if (mode.equals("Method2"))
            {
                fileManager.fileWriter(file_contents_index.toString(), "Resources\\Descriptors\\Output\\Method2\\Simple\\network_names.na");
                fileManager.fileWriter(file_contents_edges_method2.toString(), "Resources\\Descriptors\\Output\\Method2\\Simple\\network.eda");
                fileManager.fileWriter(file_contents_nodes_method2.toString(), "Resources\\Descriptors\\Output\\Method2\\Simple\\network.sif");
                fileManager.fileWriter(file_contents_similarity_method2.toString(), "Resources\\Descriptors\\Output\\Method2\\Simple\\similarity.txt");
            }
            else if (mode.equals("Method3"))
            {
                fileManager.fileWriter(file_contents_index.toString(), "Resources\\Descriptors\\Output\\Method3\\Simple\\network_names.na");
                fileManager.fileWriter(file_contents_edges_method3.toString(), "Resources\\Descriptors\\Output\\Method3\\Simple\\network.eda");
                fileManager.fileWriter(file_contents_nodes_method3.toString(), "Resources\\Descriptors\\Output\\Method3\\Simple\\network.sif");
                fileManager.fileWriter(file_contents_similarity_method3.toString(), "Resources\\Descriptors\\Output\\Method3\\Simple\\similarity.txt");
            }
//            fileManager.fileWriter(file_contents_freq.toString(), "Resources\\Descriptors\\Output\\Method2\\Simple\\network_freq.na");
//            fileManager.fileWriter(file_contents_freq.toString(), "Resources\\Descriptors\\Output\\Method3\\Simple\\network_freq.na");
        }
    }

    /**
     * Matches the resources based on their descriptors and exports the output
     * to txt files which are used by Cytoscape software to develop the semantic
     * network.
     * @param mode Tells which method of comparison is being used to measure the relevance of resources. Possible values
     * of mode are "Method2" and "Method3"
     *
     */
    public void resource_matching_using_idf(String mode)
    {
        StringBuffer file_contents_index = new StringBuffer("");
        StringBuffer file_contents_freq = new StringBuffer("");

        file_contents_index.append("names \n");
        file_contents_freq.append("freq \n");

        StringBuffer file_contents_nodes = new StringBuffer("");
        StringBuffer file_contents_edges = new StringBuffer("");
        StringBuffer file_contents_similarity = new StringBuffer("");

        if (mode.equals("Method2"))
        {
            file_contents_edges.append("similarity_2 \n");
            file_contents_similarity.append("similarity_2 \n");
        }
        else if (mode.equals("Method3"))
        {
            file_contents_edges.append("similarity_3 \n");
            file_contents_similarity.append("similarity_3 \n");
        }
        else
        {
            System.out.println("Please enter the correct value of Mode.");
            System.exit(0);
        }


        for (int i = 0; i < resources.size(); i++)
        {

            String resource1 = resources.elementAt(i).toString();
            String resource1_frequency = resource_freq.elementAt(i).toString();

            String resource1_abbreviation = resource_name_mapper(resource1);
            file_contents_index.append("n" + i + " = " + resource1_abbreviation + "\n");
            
            file_contents_freq.append("n" + i + " = " + resource1_frequency + "\n");

            Vector descriptors_resource1 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_array()[i].toString());
            int size1 = descriptors_resource1.size();

            Vector descriptors_frequencies_resource1 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_freq_array()[i].toString());
            int sum_of_all_descriptors_frequency_resource1 = vector_builder.sum_of_values_in_integer_vector(descriptors_frequencies_resource1);

            Vector tf_idf_resource1_descriptors = descriptor_processor.calculate_tf_idf(descriptors_resource1, descriptors_frequencies_resource1, sum_of_all_descriptors_frequency_resource1, resources.size());


            for (int j = i + 1; j < resources.size(); j++)
            {
                String resource2 = resources.elementAt(j).toString();

                Vector descriptors_resource2 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_array()[j].toString());
                int size2 = descriptors_resource2.size();

                Vector descriptors_frequencies_resource2 = vector_builder.vector_assigner(descriptor_processor.getDescriptors_freq_array()[j].toString());

                int sum_of_all_descriptors_frequency_resource2 = vector_builder.sum_of_values_in_integer_vector(descriptors_frequencies_resource2);

                Vector tf_idf_resource2_descriptors = descriptor_processor.calculate_tf_idf(descriptors_resource2, descriptors_frequencies_resource2, sum_of_all_descriptors_frequency_resource2,resources.size());

                Double matching_value = 0.0;
                
                if (mode.equals("Method2"))
                {
                    matching_value = descriptor_processor.match_descriptors_using_idf(descriptors_resource1, tf_idf_resource1_descriptors, descriptors_resource2, tf_idf_resource2_descriptors);
                    matching_value = (double) (matching_value) / (size1*size2);
                }
                else if (mode.equals("Method3"))
                {
                    matching_value = descriptor_processor.match_descriptors_using_idf_of_lexical_profiles(descriptors_resource1, tf_idf_resource1_descriptors, descriptors_resource2, tf_idf_resource2_descriptors);
                    matching_value = (double) (matching_value) / (size1*size2);
                }
                else
                {
                    System.out.println("Incorrect value of Mode is selected \n" +
                            "Please select one of these: \n" +
                            "Method1 \n" +
                            "Method2 \n" +
                            "Method3 \n");
                    System.exit(0);
                }


                if (matching_value > 0)
                {
                    file_contents_edges.append("n" + i + " (s) n" + j + " = " + matching_value + "\n");
                    file_contents_similarity.append(resource1 + " (sim) " + resource2 + " = " + matching_value + "\n");
                    file_contents_nodes.append("n" + i + " s n" + j + "\n");
                }
            }

            fileManager.fileWriter(file_contents_index.toString(), "Resources\\Descriptors\\Output\\" + mode + "\\tf_idf\\network_names.na");
            fileManager.fileWriter(file_contents_edges.toString(), "Resources\\Descriptors\\Output\\" + mode + "\\tf_idf\\network.eda");
            fileManager.fileWriter(file_contents_nodes.toString(), "Resources\\Descriptors\\Output\\" + mode + "\\tf_idf\\network.sif");
//            fileManager.fileWriter(file_contents_freq.toString(), "Resources\\Descriptors\\Output\\" + mode + "\\tf_idf\\network_freq.na");
            fileManager.fileWriter(file_contents_similarity.toString(), "Resources\\Descriptors\\Output\\" + mode + "\\tf_idf\\similarity.txt");
        }
    }



    /**
     * Matches all the resources (retrieved using extract_descriptors method)
     * on basis of their lexical profiles
     */
    public void resource_matching_using_lexical_profiles(String similarity_metric)
    {
        Vector temp1, temp2;
        StringBuffer file_contents_lexical = new StringBuffer("");

        for (int i = 0; i < resources.size(); i++)
        {
            String resource1 = resources.elementAt(i).toString();

            for (int j = i + 1; j < resources.size(); j++)
            {
                double cosine = 0.0;
                double dice = 0.0;

                String resource2 = resources.elementAt(j).toString();

                temp1 = vector_builder.vector_assigner(resource_profile_array[i].toString());
                temp2 = vector_builder.vector_assigner(resource_profile_array[j].toString());

                int size1 = temp1.size();
                int size2 = temp2.size();
                temp1.retainAll(temp2);

                if ((temp1.size() == 1) && (temp1.contains("of")))
                {
                    // Do nothing
                }
                else if (similarity_metric.equals("COSINE"))
                {
                    cosine = (double) (temp1.size()) / ((size1*size2));
                    if (cosine > 0)
                    {
                        file_contents_lexical.append("\n" + resource1 + " (s1) " + resource2 + " = " + cosine);
                    }
                }
                else if (similarity_metric.equals("DICE"))
                {
                    dice = (double) (2 * temp1.size()) / (size1 + size2);
                    if (dice > 0)
                    {
                        file_contents_lexical.append("\n" + resource1 + " (s1) " + resource2 + " = " + dice);
                    }
                }
                else
                {
                    System.out.println("Choose correct value of Similarity metric");
                }
            }
            fileManager.fileWriter(file_contents_lexical.toString(), "Resources\\Descriptors\\Output\\Method1\\lexical.na");
        }
    }


    /*
     * It maps the resource name to suitable abbreviation
     * @param resource_name Given resource name which is to be mapped to its abbreviation
     */
    private String resource_name_mapper(String resource_name)
    {
        if (resource_name.equals("Gene ontology"))
        {
            return "GO";
        }
        else if (resource_name.equals("Support vector machine"))
        {
            return "SVM";
        }
        else if (resource_name.equals("Protein data bank"))
        {
            return "PDB";
        }
        else if (resource_name.equals("Hidden Markov model"))
        {
            return "HMM";
        }
        else if (resource_name.equals("Principal components analysis"))
        {
            return "PCA";
        }
        else if (resource_name.equals("Position-specific scoring matrix"))
        {
            return "PSSM";
        }
        else if (resource_name.equals("Self organising map"))
        {
            return "SOM";
        }
        else if (resource_name.equals("Medical subject headings"))
        {
            return "MeSH";
        }
        else if (resource_name.equals("Neural network"))
        {
            return "NN";
        }
        else if (resource_name.equals("Markov chain Monte Carlo"))
        {
            return "MCMC";
        }
        else if (resource_name.equals("Expression profile"))
        {
            return "Expression profile";
        }
        else if (resource_name.equals("Basic local alignment search tool"))
        {
            return "BLAST";
        }
        else if (resource_name.equals("Phylogenetic tree"))
        {
            return "Phylogenetic tree";
        }
        else if (resource_name.equals("Structural classification of proteins"))
        {
            return "SCOP";
        }
        else if (resource_name.equals("Kyoto encyclopaedia of genes and genomes"))
        {
            return "KEGG";
        }
        else if (resource_name.equals("Clusters of orthologous groups"))
        {
            return "COG";
        }
        else if (resource_name.equals("ChIp-chip data"))
        {
            return "ChIp-chip data";
        }
        else if (resource_name.equals("Pairwise alignment"))
        {
            return "Pairwise alignment";
        }

        else if (resource_name.equals("kalign algorithm"))
        {
            return "KA";
        }

        else if (resource_name.equals("clustalw program"))
        {
            return "CP";
        }

        else
            return "invalid";

    }
}